package main

/**
case1:指针

第一种方式
go build -gcflags '-m -l' case_pointer.go
# command-line-arguments
./case_pointer.go:38:9: &User{...} escapes to heap
./case_pointer.go:46:12: new(string) does not escape

第二种方式
go tool compile -S case_pointer.go

汇编代码里有runtime.newobject(SB)
...
  0x0018 00024 (main.go:9)        SUB     $8, RSP, R29
        0x001c 00028 (main.go:9)        FUNCDATA        ZR, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
        0x001c 00028 (main.go:9)        FUNCDATA        $1, gclocals·f207267fbf96a0178e8758c6e3e0ce28(SB)
        0x001c 00028 (main.go:9)        FUNCDATA        $2, "".main.stkobj(SB)
        0x001c 00028 (main.go:10)       MOVD    $type."".Test(SB), R0
        0x0024 00036 (main.go:10)       MOVD    R0, 8(RSP)
        0x0028 00040 (main.go:10)       PCDATA  $1, ZR
        0x0028 00040 (main.go:10)       CALL    runtime.newobject(SB)
        0x002c 00044 (main.go:10)       MOVD    16(RSP), R0
        0x0030 00048 (main.go:11)       STP     (ZR, ZR), ""..autotmp_13-16(SP)

...

分析结果：
GetUserInfo() 返回的是指针对象，引用被返回到了方法之外了。因此编译器会把该对象分配到堆上，而不是栈上。
如果把下面返回的User改为非指针，就不会逃逸

str 没有被作用域之外所引用，而这里作用域仍然保留在 main 中，因此它没有发生逃逸。
 */
type User struct {
	ID     int64
	Name   string
	Avatar string
}

func GetUserInfo() *User {
	return &User{ID: 13746731, Name: "EDDYCJY", Avatar: "https://avatars0.githubusercontent.com/u/13746731"}
}

func main() {
	_ = GetUserInfo()

	str := new(string)
	*str = "EDDYCJY"
}